<?php
/**
 * 核心 - [调试]类
 *
 * @version $Id: Debugger.php 169 2014-03-10 06:54:42Z linsir123 $
 * @package Core
 */
class Debugger
{
	/**
	 * 配置
	 *
	 * @var array
	 */
	public $conf = array();

	/**
	 * 是否开启调试
	 *
	 * @var bool
	 */
	private $_flag = false;

	/**
	 * 调试日志数
	 *
	 * @var int
	 */
	private $_count;

	/**
	 * 开始时间
	 *
	 * @var int
	 */
	private $_timeStart;

	/**
	 * 日志队列
	 *
	 * @var array
	 */
	private $_logList;

	/**
	 * 开发模式
	 */
	const Dev = 1;

	/**
	 * 线上模式
	 */
	const Online = 2;

	/**
	 * 构造函数
	 *    1、确认开启状态
	 *    2、确认处理方式
	 */
	public function __construct()
	{
		$this->conf = App::o("app.debugger");
		$this->_flag = ! empty($this->conf['mode'])
			&& in_array($this->conf['mode'], array(self::Dev, self::Online));

		switch ($this->conf['mode']) {
			case self::Online:
				/// 2.1
				$maxRand = intval($this->conf['online']['maxRand']);
				if ($maxRand > 1)
					$this->_flag = mt_rand(1, $maxRand) == 1;

				/// 2.2
				$routes = $this->conf['online']['routes'];
				if (is_array($routes) && ! empty($routes)) {
					$route = strtolower(App::$I->getRequest()->route);
					$routes = array_map('strtolower', $routes);
					$this->_flag = in_array($route, $routes);
				}
				break;

			default:
				break;
		}

		///
		if ($this->_flag)
			App::$I->getHook()->addHook('end', array($this, 'handlerLog'));
	}

	/**
	 * 处理日志
	 * // 由系统调用
	 */
	public function handlerLog()
	{
		if (! $this->_flag)
			return;

		/// 1
		$totalTime = $this->_timerStop(TIME_START);
		$content = sprintf("\nProcess execution %f seconds, the space occupied %s, Detail:\r\n%s\r\n",
			$totalTime,
			$this->_getMemoryUsage(),
			implode("\r\n", $this->_logList));

		/// 2
		switch ($this->conf['mode']) {
			case self::Online:
				$maxTime = floatval($this->conf['online']['maxTime']);
				if ($totalTime >= $maxTime) {
					///
					App::$I->getLog()->write($content, 'runtime/debug');
				}
				break;

			default:
				echo nl2br($content);
				break;
		}
	}

	/**
	 * 记录调试内容
	 *
	 * @param string $message
	 */
	public function log($message)
	{
		if (! $this->_flag)
			return;

		///
		$this->_logList[] = sprintf("%d: [%s s] %s",
			++$this->_count,
			$this->_timerStop(),
			$message);
	}

	/**
	 * 开启计时器
	 */
	public function timerStart()
	{
		if (! $this->_flag)
			return;

		///
		$this->_timeStart = $this->_getMtime();
	}

	/**
	 * 返回执行时间
	 *
	 * @param null $microtime
	 *
	 * @return float
	 */
	private function _timerStop($microtime = null)
	{
		if (empty($microtime))
			$timeStart = $this->_timeStart;
		else
			$timeStart = $this->_getMtime($microtime);

		///
		$tmp = $this->_getMtime() - $timeStart;

		return number_format($tmp, 6);
	}

	/**
	 * 返回`microtime`
	 *
	 * @param null $microtime
	 *
	 * @return float
	 */
	private function _getMtime($microtime = null)
	{
		if (empty($microtime))
			$microtime = microtime();

		///
		list($usec, $sec) = explode(" ", $microtime);

		return ((float)$usec + (float)$sec);
	}

	/**
	 * 取得进程占用内存
	 *
	 * @param bool $real
	 *
	 * @return string
	 */
	private function _getMemoryUsage($real = false)
	{
		$unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
		$size = memory_get_usage($real);

		return @round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $unit[$i];
	}
}
